﻿using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace K9Nano.Caching
{
    [Obsolete("Use ITypedCache", true)]
    public interface ICache
    {
        #region Set

        bool Set([NotNull]string key, object value, int expireSeconds = -1);

        bool Set([NotNull]string key, object value, TimeSpan expire) => Set(key, value, (int)expire.TotalSeconds);

        Task<bool> SetAsync([NotNull]string key, object value, int expireSeconds = -1, CancellationToken cancellation = default);

        Task<bool> SetAsync([NotNull]string key, object value, TimeSpan expire, CancellationToken cancellation = default) 
            => SetAsync(key, value, (int)expire.TotalSeconds, cancellation);

        #endregion

        #region Get

        T Get<T>([NotNull]string key, int refreshSeconds = 0);

        bool TryGet<T>([NotNull]string key, out T result, int refreshSeconds = 0);

        T Get<T>([NotNull]string key, TimeSpan refresh) 
            => Get<T>(key, (int)refresh.TotalSeconds);

        Task<T> GetAsync<T>([NotNull]string key, int refreshSeconds = 0, CancellationToken cancellation = default);

        Task<T> GetAsync<T>([NotNull]string key, TimeSpan refresh, CancellationToken cancellation = default) 
            => GetAsync<T>(key, (int)refresh.TotalSeconds, cancellation);

        async Task<T> GetOrCreateAsync<T>([NotNull] string key, TimeSpan expire, Func<Task<T>> creator, CancellationToken cancellation = default)
        {
            var result = await GetAsync<T>(key, 0, cancellation);
            if (result == null)
            {
                result = await creator();

                await SetAsync(key, result, expire, cancellation);
            }
            return result;
        }

        T GetOrCreate<T>([NotNull] string key, TimeSpan expire, Func<T> creator)
        {
            var result = Get<T>(key, 0);
            if (result == null)
            {
                result = creator();

                Set(key, result, expire);
            }
            return result;
        }

        #endregion

        #region Remove

        void Remove([NotNull]params string[] key);

        Task RemoveAsync([NotNull]string key, CancellationToken cancellation = default);

        Task RemoveAsync([NotNull]string[] keys, CancellationToken cancellation = default);

        /// <summary>
        /// 通配符删除Key
        /// </summary>
        /// <param name="pattern">支持 a*, *a, a*b </param>
        void RemovePattern([NotNull]string pattern);

        /// <summary>
        /// 通配符删除Key
        /// </summary>
        /// <param name="pattern">支持 a*, *a, a*b </param>
        Task RemovePatternAsync([NotNull]string pattern, CancellationToken cancellation = default);

        void RemoveByPrefix([NotNull]string prefix)
            => RemovePattern(prefix + "*");

        Task RemoveByPrefixAsync([NotNull]string prefix, CancellationToken cancellation = default) 
            => RemovePatternAsync(prefix + "*", cancellation);

        #endregion

        #region Expire

        bool Expire([NotNull]string key, int seconds);

        Task<bool> ExpireAsync([NotNull]string key, int seconds, CancellationToken cancellation = default);

        bool Expire([NotNull]string key, TimeSpan expire) => Expire(key, (int)expire.TotalSeconds);

        Task<bool> ExpireAsync([NotNull]string key, TimeSpan expire, CancellationToken cancellation = default)
            => ExpireAsync(key, (int)expire.TotalSeconds, cancellation);

        #endregion
    }
}